package com.cskaoyan.javase._2inner._0introduction;

/**
 * 引例
 * 我们现在做一个应用程序，
 *      需要描述一台电脑中的CPU，对于电脑而言，该怎么去描述这个CPU呢？
 * 分析：
 * 我们可以创建两个类，一个描述Computer，一个描述CPU。
 * 但这样明显是有问题的：
 *      1.CPU是电脑中最重要的组件，但它脱离电脑存在就是一粒沙子。
 *      这意味着CPU对象，应仅存在于Computer类的内部。
 *      而不应该能够在Computer类之外的其他类中能够创建对象.
 *      2.CPU可以控制计算机的一切硬件资源。
 *       这意味CPU对象能够操控，Computer类中的所有成员，无论私有。
 *
 * 以上两个需求,在开发中并不少见:
 *      1.要求某个类的对象仅存在于某个类中
 *      2.要求两个类之间访问成员要不受权限限制
 * 但是很明显,两个单独定义的class是不可能实现这两个需求的.
 *      定义普通类CPU是不能完成需求的，因为：
 *      普通类没有私有概念，不可能控制仅能在Computer内部创建对象。
 *      普通类不可能直接访问，其它类的私有成员。
 *
 * 显然CPU类不应该是一个普通类，不应该是一个独立的类
 * --->
 * 不再将CPU类定义为一个独立的类，而是将它放入Computer类的类体中
 * --->
 * 将这个CPU类,近似的看成是一个Computer类的成员
 * --->
 * 于是:
 * 在其它类内部的类，就有了私有概念,一个类就有了四种访问权限,
 *      这时私有化该类,那么该类就对外不可见了.
 * 既然已经成为了成员，成为了"自己人"，
 * 那么就不再受限于权限控制了，
 * 内部类就可以访问包裹它的类的所有成员，包括私有。
 *
 * 上述两条，其实就是（成员位置）内部类的主要特点。也说明了使用内部类的主要场景：
 *      1.内部类是一种比类更加极致的封装思想体现,
 *          内部类的成员不仅被内部类自身保护,还被包裹着它的类保护。
 *      2.内部类和包裹它的类互相成为了"好兄弟"，互相访问成员都不受访问权限限制。
 * 当你有以上使用场景时，就可以考虑使用内部类。
 *
 * 内部类的定义:
 * 在Java语言中类可以嵌套定义，广义的内部类指的是定义在另一类当中的一个类。
 * 当然内部类有很多，如果按照内部类在类中定义的位置不同，可以分为：
 *      1.定义在成员位置的内部类，包括成员内部类，静态内部类。
 *      2.定义在局部位置的内部类，包括局部内部类，匿名内部类，Lambda表达式。
 *
 * 但是我们在学习的时候，不按定义位置来学习。
 *      我们按照它是一个类，还是直接创建一个对象来分类：
 *      1.语法定义了一个类，包括成员内部类、静态内部类和局部内部类。
 *          使用这些内部类,还需要创建对象,因为它们是在另外一个类的内部定义了一个类.
 *      2.语法直接创建了一个对象,包括匿名内部类和Lambda表达式.
 *          由于已经通过语法创建了对象，可以直接使用。
 *
 * 为了上课方便，我们需要统一口径，在内部类课程当中，我们统一规定：
 *      1.像CPU这种，定义在别的类的内部的类，我们称之为内部类。（inner）
 *      2.像Computer这种，包裹内部类的，我们称之为外围类。（enclosed）
 *      3.Demo这种类我们称之为外部类或者其他类。（outside）
 *
 * 最后说一点:
 *      内部类的语法相对于之前的Java语法,是比较复杂的
 *      初学内部类,以"搞懂语法,会用语法"为主,不要过多的思考用途
 *      而且:
 *          成员内部类和静态内部类实际开发中使用较少,大多见于一些源码当中
 *          局部内部类的使用也非常少见,但学习局部内部类是学习匿名内部类和Lambda表达式的前提
 *          而匿名内部类和Lambda表达式在开发中是最常见的内部类,尤其是Lambda表达式
 *              Lambda表达式语法简洁优雅,写出的代码非常简洁,在Java8当中是相当重要的语法.
 *
 *
 * @since 16:21
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        // CPU cpu = new CPU();
    }
}

class Computer {
    private CPU cpu;

    public class CPU {
        public int num;
    }
}

/*
class CPU {

}*/
